﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

namespace Edge.OAuth
{
    public class OAuth2
    {
        public enum AccessTokenType
        {
            Raw,
            Dictionary,
            JsonDictionary,
            OAuth2Token
        }
        public const string OAUTH_CLIENT_ID = "client_id";
        public const string OAUTH_REDIRECT_URI = "redirect_uri";
        public const string OAUTH_EXPIRES = "expires_in";
        public const string OAUTH_ACCESS_TOKEN = "access_token";
        public const string OAUTH_RESPONSE_TYPE = "response_type";
        public const string OAUTH_RESPONSE_TYPE_TOKEN = "token";
        public const string OAUTH_RESPONSE_TYPE_CODE = "code";
        public const string OAUTH_CODE = "code";
        public const string OAUTH_GRANT_TYPE = "grant_type";
        public const string OAUTH_GRANT_TYPE_VALUE = "authorization_code";
        public const string OAUTH_TOKEN = "oauth_token";

        public OAuth2()
        {
        }

        public OAuth2(string client_id, string secret_key, string auth_url, string token_url, string redirect_uri)
        {
            _ClientId = client_id;
            _SecretKey = secret_key;
            _AuthUrl = auth_url;
            _TokenUrl = token_url;
            _RedirectURI = redirect_uri;
        }

        public string GetAuthCode(Dictionary<string, string> additional)
        {
            return GetAuthCode(_AuthUrl, additional);
        }

        public string GetAuthCode(string auth_url, Dictionary<string, string> additional)
        {
            Dictionary<string, string> parameters = additional;
            parameters.Add(OAUTH_CLIENT_ID, _ClientId);
            parameters.Add(OAUTH_RESPONSE_TYPE, OAUTH_RESPONSE_TYPE_CODE);
            if (!string.IsNullOrEmpty(_RedirectURI))
                parameters.Add(OAUTH_REDIRECT_URI, _RedirectURI);
            return string.Format("{0}{1}", auth_url, OAuthCommonUtils.GetParametersString(parameters));
        }
        string _ClientId = string.Empty;
        public string ClientId
        {
            get
            {
                return _ClientId;
            }
            set
            {
                _ClientId = value;
            }
        }

        string _SecretKey = string.Empty;
        public string SecretKey
        {
            get
            {
                return _SecretKey;
            }
            set
            {
                _SecretKey = value;
            }
        }

        string _AuthUrl = string.Empty;
        public string AuthUrl
        {
            get
            {
                return _AuthUrl;
            }
            set
            {
                _AuthUrl = value;
            }
        }

        string _TokenUrl = string.Empty;
        public string TokenUrl
        {
            get
            {
                return _TokenUrl;
            }
            set
            {
                _TokenUrl = value;
            }
        }

        string _Code = string.Empty;
        public string Code
        {
            get
            {
                return _Code;
            }
            set
            {
                _Code = value;
            }
        }

        string _Token = string.Empty;
        public string Token
        {
            get
            {
                return _Token;
            }
            set
            {
                _Token = value;
            }
        }

        string _RedirectURI = string.Empty;
        public string RedirectURI
        {
            get
            {
                return _RedirectURI;
            }
            set
            {
                _RedirectURI = value;
            }
        }
        public string GetAuthCode()
        {
            return GetAuthCode(_AuthUrl);
        }

        public string GetAuthCode(string auth_url)
        {
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add(OAUTH_CLIENT_ID, _ClientId);
            parameters.Add(OAUTH_RESPONSE_TYPE, OAUTH_RESPONSE_TYPE_CODE);
            if (!string.IsNullOrEmpty(_RedirectURI))
                parameters.Add(OAUTH_REDIRECT_URI, _RedirectURI);
            return string.Format("{0}{1}", auth_url, OAuthCommonUtils.GetParametersString(parameters));
        }
        public OAuth2Token GetAccessToken(AccessTokenType att)
        {
            return GetAccessToken(_Code, null, att);
        }

        public OAuth2Token GetAccessToken(Dictionary<string, string> additional, AccessTokenType att)
        {
            return GetAccessToken(_Code, additional, att);
        }

        public OAuth2Token GetAccessToken(string code, Dictionary<string, string> additional, AccessTokenType att)
        {
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add(OAUTH_GRANT_TYPE, OAUTH_GRANT_TYPE_VALUE);
            parameters.Add(OAUTH_CODE, code);
            parameters.Add(OAUTH_CLIENT_ID, _ClientId);
            if (!string.IsNullOrEmpty(_RedirectURI))
                parameters.Add(OAUTH_REDIRECT_URI, _RedirectURI);
            if (additional != null)
                foreach (var item in additional)
                    parameters.Add(item.Key, item.Value);

            string raw_token = OAuthCommonUtils.SendPostRequest(_TokenUrl, OAuthCommonUtils.GetParametersString(parameters).Remove(0, 1));
            OAuth2Token token = null;
            switch (att)
            {
                case AccessTokenType.JsonDictionary:
                    token = new OAuth2Token();
                    JavaScriptSerializer s = new JavaScriptSerializer();
                    token.dictionary_token = s.Deserialize<Dictionary<string, string>>(raw_token);
                    break;
                case AccessTokenType.Raw:
                    token = new OAuth2Token();
                    token.raw_token = raw_token;
                    break;
                case AccessTokenType.Dictionary:
                    token = new OAuth2Token();
                    string[] p = raw_token.Split('&');
                    foreach (string item in p)
                    {
                        string[] key_value = item.Split('=');
                        token.dictionary_token.Add(key_value[0], key_value[1]);
                    }
                    break;
                case AccessTokenType.OAuth2Token:
                    try
                    {
                        JavaScriptSerializer serializer = new JavaScriptSerializer();
                        token = serializer.Deserialize<OAuth2Token>(raw_token);
                        token.raw_token = raw_token;
                    }
                    catch (Exception exc)
                    {
                    }
                    break;
            }

            return token;
        }
    }
    public class OAuth2Token
    {
        public string access_token
        {
            get;
            set;
        }

        public int? expires_in
        {
            get;
            set;
        }

        public string refresh_token
        {
            get;
            set;
        }

        public string x_mailru_vid
        {
            get;
            set;
        }

        public string raw_token
        {
            get;
            set;
        }

        Dictionary<string, string> _dictionary_token = new Dictionary<string, string>();
        public Dictionary<string, string> dictionary_token
        {
            get
            {
                return _dictionary_token;
            }
            set
            {
                _dictionary_token = value;
            }
        }

    
    }

}
